﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using TrailMapManager.Communication;

namespace TrailMapManager.Common
{
    public class CommunicationManager : BaseViewLogic
    {
        #region properties

        public int PendingCommandsCount
        {
            get { return CommandQueue.Count; }
        }

        
        private ObservableCollection<MapInformation> _maps;
        public ObservableCollection<MapInformation> Maps
        {
            get
            {

                if (_maps == null)
                {
                    _maps = new ObservableCollection<MapInformation>();
                    _maps.CollectionChanged += (s, args) => { NotifyPropertyChanged("MapsCount"); };
                }
                return _maps;

            }
        }

        public int MapsCount
        {
            get
            {
                if (Maps != null)
                {
                    return Maps.Count;
                }
                return 0;
            }
        }


        private Queue<TrailCommand> _commandQueue;
        public Queue<TrailCommand> CommandQueue
        {
            get
            {
                if (_commandQueue == null)
                {
                    _commandQueue = new Queue<TrailCommand>();
                }
                return _commandQueue;
            }
        }


        private string _phoneName;
        public string PhoneName
        {
            get { return _phoneName; }
            set { _phoneName = value; NotifyPropertyChanged("PhoneName"); }
        }
        #endregion

        static object staticLockObject = new object();
        private static CommunicationManager _instance;
        public static CommunicationManager Instance
        {
            get
            {
                lock (staticLockObject)
                {
                    if (_instance == null)
                    {
                        _instance = new CommunicationManager();
                        _instance.Init();
                    }
                    return _instance;
                }
            }
        }
        ServiceHost host;

        private CommunicationManager()
        {

        }

        private void Init()
        {
            host = new ServiceHost(typeof(TrailMapCommunication));
            try
            {
                //Allow Port
                string showResult = RunCMD.Run("netsh", "advfirewall firewall show rule name=\"TrailMapManager\"");
                if (!showResult.Contains("TrailMapManager"))
                {
                    RunCMD.Run("netsh", "advfirewall firewall add rule name=\"TrailMapManager\" dir=in action=allow protocol=TCP localport=12345");
                }
                host.Open();
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Cant create server: " + ex.Message);
            }
        }

        internal bool NewConnection(string phoneName, long maxSpace, long freeSpace)
        {
            PhoneName = phoneName;

            Poi.PoiManager.Instance.ClearAll();
            Track.TrailTrackManager.Instance.ClearAll();

            CommandQueue.Enqueue(new TrailCommand() { Type = CommandType.GetMapList });
            CommandQueue.Enqueue(new TrailCommand() { Type = CommandType.GetPoiList });
            CommandQueue.Enqueue(new TrailCommand() { Type = CommandType.GetTrackList });

            NotifyPropertyChanged("PendingCommandsCount");
            return true;
        }

        public void AddNewCommandToQueue(TrailCommand command)
        {
            CommandQueue.Enqueue(command);
            NotifyPropertyChanged("PendingCommandsCount");
        }

        internal void AddMapList(List<MapInformation> maps)
        {
            if (Maps.Count > 0) ;
            {
                Maps.Clear();
            }
            foreach (var map in maps)
            {
                Maps.Add(map);
            }
        }

        internal TrailCommand GetNewCommand()
        {
            if (CommandQueue.Count > 0)
            {
                var command = CommandQueue.Dequeue();
                NotifyPropertyChanged("PendingCommandsCount");
                return command;

            }
            return null;

        }

        public void AddMapToUpload(string fileName)
        {
            CommandQueue.Enqueue(new DownloadMapCommand()
            {
                ServerFilePath = fileName,
                Type = CommandType.DownloadMap,
                FileName = fileName.Split("\\".ToArray(), StringSplitOptions.RemoveEmptyEntries).Last(),
            });
        }
        //public void AddMapToUpload(System.IO.FileStream fs)
        //{
        //    //new Task(
        //    //    () =>
        //    //    {
        //    //        HttpListener listener = new HttpListener();
        //    //        listener.Prefixes.Add("http://192.168.1.232:80/valami/");

        //    //        listener.Start();
        //    //        HttpListenerContext context = listener.GetContext();
        //    //        HttpListenerRequest request = context.Request;
        //    //        // Obtain a response object.
        //    //        HttpListenerResponse response = context.Response;
        //    //        // Construct a response. 
        //    //        int count = 0;
        //    //        byte[] buffer = new byte[1024];
        //    //        response.ContentLength64 = buffer.Length;
        //    //        System.IO.Stream output = response.OutputStream;
        //    //        do
        //    //        {
        //    //            context = listener.GetContext();
        //    //            request = context.Request;
        //    //            count = fs.Read(buffer, 0, 1024);

        //    //            // Get a response stream and write the response to it.

        //    //            output.Write(buffer, 0, buffer.Length);
        //    //        } while (count == 1024);
        //    //        // You must close the output stream.
        //    //        output.Close();
        //    //        listener.Stop();
        //    //    }).Start();


        //    HttpListener listener = new HttpListener();
        //    listener.Prefixes.Add("http://192.168.1.232:85/valami/");
        //    listener.Start();
        //    Task.Factory.StartNew(() =>
        //    {
        //        HttpListenerContext context = listener.GetContext();
        //        Task.Factory.StartNew((ctx) =>
        //        {
        //            WriteFile((HttpListenerContext)ctx, fs);
        //            listener.Close();
        //        }, context, TaskCreationOptions.LongRunning);


        //    }, TaskCreationOptions.LongRunning);

        //    CommandQueue.Enqueue(new DownloadMapCommand()
        //    {
        //        Uri = "http://192.168.1.232:85/valami/dfg",
        //        Type = CommandType.DownloadMap,
        //        Map = new MapInformation()
        //        {
        //            FileName = fs.Name,
        //        }
        //    });
        //}

        //void WriteFile(HttpListenerContext ctx, FileStream fs)
        //{
        //    var response = ctx.Response;
        //    //using (FileStream fs = File.OpenRead(@"..."))
        //    //{

        //    //response is HttpListenerContext.Response...
        //    response.ContentLength64 = fs.Length;
        //    response.SendChunked = false;
        //    response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet;
        //    response.AddHeader("FileName", fs.Name.Split("\\".ToArray(), StringSplitOptions.RemoveEmptyEntries).Last());

        //    byte[] buffer = new byte[64 * 1024];
        //    int read;
        //    using (BinaryWriter bw = new BinaryWriter(response.OutputStream))
        //    {
        //        while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
        //        {
        //            bw.Write(buffer, 0, read);
        //            bw.Flush(); //seems to have no effect
        //        }

        //        bw.Close();
        //    }

        //    response.StatusCode = (int)HttpStatusCode.OK;
        //    response.StatusDescription = "OK";
        //    response.OutputStream.Close();
        //}
        //}

        internal FileTransferSegment GetFileSegment(FileTransferSegmentRequest request)
        {
            using (FileStream fs = new FileStream(request.FilePath, FileMode.Open))
            {
                FileTransferSegment fts = new FileTransferSegment()
                {
                    Buffer = new byte[request.Length],
                    ServerFilePath = request.FilePath,
                    FileName = fs.Name.Split("\\".ToArray(), StringSplitOptions.RemoveEmptyEntries).Last()
                };

                fs.Seek(request.StartIndex, SeekOrigin.Begin);
                int readedByte = fs.Read(fts.Buffer, 0, request.Length);
                if (readedByte != request.Length)
                {
                    fts.isFinish = true;
                }
                fts.Length = readedByte;
                fts.StartIndex = request.StartIndex;
                //NotifyProgressChange(fs.Length, fs.Position);
                fs.Close();
                return fts;
            }

        }
    }
}
